﻿<?PHP
  class Settings{

    protected $area               = "global";
    protected $areaType           = "global";
    protected $dir                = "global";
    protected $parent             = null;
    protected $properties         = array();
    protected static $instances   = array();
    protected static $default     = null;
    protected static $root        = null;
    public static $allowFileCache = true;

    /**
     *
     * @param string $property
     * @param int $role
     * @param boolean $allowCache
     * @return string 
     */
    public function get($property, $role = null, $allowCache = true){
      $res = null;
      if(!$role){
        $role = User::Current()->role->ID;
      }
      if(isset($this->properties[$property][$role]) && $allowCache){
        $res = $this->properties[$property][$role];
      }
      else{
        $res = $this->getFromDB($property, $role);
        if(!$res && $this->parent != null){
          $res = $this->parent->get($property,$role, $allowCache);
        }
        if($allowCache){
          $this->properties[$property][$role] = $res;
        }
      }
      return $res;
    }

    /**
     *
     * @param string $property
     * @param int $role
     * @return string 
     */
    protected function getFromDB($property, $role){
      $area     = DataBase::Current()->EscapeString($this->area);
      $areaType = DataBase::Current()->EscapeString($this->areaType);
      $dir      = DataBase::Current()->EscapeString($this->dir);
      $property = DataBase::Current()->EscapeString($property);
      $sql      = "";
      if(!User::Current()->isGuest()){
       $sql = "SELECT value FROM {'dbprefix'}settings WHERE role = '".$role."' AND area = '".$area."' AND areaType = '".$areaType."' AND dir = '".$dir."' AND property = '".$property."' UNION ";
      }
      $sql .= "SELECT value FROM {'dbprefix'}settings WHERE role = '3' AND area = '".$area."' AND areaType = '".$areaType."' AND dir = '".$dir."' AND property = '".$property."'";
      $res = DataBase::Current()->ReadField($sql);
      if(!isset($this->properties[$property])){
          $this->properties[$property] = array();
      }
      $this->properties[$property][$role] = $res;
      return $res;
    }

    /**
     *
     * @param string $property
     * @param string $value
     * @param int $role
     * @return boolean 
     */
    public function set($property,$value,$role = 3){
      $valueChanged = $this->get($property) != $value;
      $area     = DataBase::Current()->EscapeString($this->area);
      $areaType = DataBase::Current()->EscapeString($this->areaType);
      $property = DataBase::Current()->EscapeString($property);
      $value    = DataBase::Current()->EscapeString($value);
      $role     = DataBase::Current()->EscapeString($role);
      $dir      = DataBase::Current()->EscapeString($this->dir);
      $valueChanged = $valueChanged || ($dir == "global" && $area == "global" && $areaType == "global" && $role == "3");
      $allUserData = DataBase::Current()->ReadRow("SELECT * FROM  {'dbprefix'}settings WHERE area = '".$area."' AND areaType = '".$areaType."' AND property = '".$property."'", false);
      if($valueChanged){
        $exists = DataBase::Current()->ReadField("SELECT COUNT(*) FROM {'dbprefix'}settings WHERE area = '".$area."' AND areaType = '".$areaType."' AND property = '".$property."' AND role = '".$role."' AND dir = '".$dir."'") > 0;
        if($exists){
          $res = DataBase::Current()->Execute("UPDATE {'dbprefix'}settings SET value = '".$value."' WHERE area = '".$area."' AND areaType = '".$areaType."' AND property = '".$property."' AND role = '".$role."' AND dir = '".$dir."'");
         }
        else{
          $res = DataBase::Current()->Execute("INSERT INTO {'dbprefix'}settings (value,area,areaType,property,role,description,type,dir) VALUES ('".$value."', '".$area."', '".$areaType."', '".$property."', '".$role."','".$allUserData->description."','".$allUserData->type."','".$dir."')");
        }
      }
      else{
        DataBase::Current()->Execute("DELETE FROM {'dbprefix'}settings WHERE area = '".$area."' AND areaType = '".$areaType."' AND property = '".$property."' AND role = '".$role."' AND dir = '".$dir."'");
        $res = true;
      }
      Cache::clear();
      return $res;
    }

    /**
     *
     * @param string $area 
     */
    protected function setArea($area){
      $this->area = $area;
    }

    /**
     *
     * @param string $area 
     */
    protected function setAreaType($area){
      $this->areaType = $area;
    }

    /**
     *
     * @param string $dir 
     */
    protected function setDir($dir){
      $this->dir = $dir;
    }

    /**
     *
     * @return Settings
     */
    public static function getInstance(){
      if(!isset(self::$default)){
        if(!isset(self::$instances["global"]["global"]["global"])){
            $res = new Settings();
            self::$instances["global"]["global"]["global"] = $res;
            if(isset($_GET['include'])){
              Settings::setDefaultInstance(Settings::getInstance()->dir(sys::getAlias()."§page"));
            }
            else{
              Settings::setDefaultInstance(Settings::getInstance()->dir("home§page"));
            }
        }
        else{
          $res = self::$instances["global"]["global"]["global"];
        }
        self::$root = $res;
      }
      else{
        $res = self::$default;
      }
      return $res;
    }

    /**
     *
     * @return Settings
     */
    public static function getRootInstance(){
      $res = null;
      if(!isset(self::$root)){
        $res = self::getInstance();
      }
      else{
        $res = self::$root;
      }
      return $res;
    }

    /**
     *
     * @param Settings $settings 
     */
    public static function setDefaultInstance(Settings $settings){
      self::$default = $settings;
    }

    /**
     *
     * @param string $areaType
     * @param string $area
     * @return Settings
     */
    public function specify($areaType = "global",$area = "global"){
      if(!isset(self::$instances[$areaType][$area][$this->dir])){
        $res = Settings::getCached($area,$areaType,$this->dir);
        $res->parent = $this;
        self::$instances[$areaType][$area][$this->dir] = $res;
      }
      else{
        $res = self::$instances[$areaType][$area][$this->dir];
      }
      return $res;
    }

    /**
     *
     * @param string $dir
     * @param Settings $settings
     * @return Settings 
     */
    public function dir($dir,$settings = null){
      if($settings == null){
        $settings = $this;
      }
      if(substr($dir,0,1) == "/"){
        $dir = substr($dir,1);
      }
      if(!isset(self::$instances[$this->areaType][$this->area][$this->dir."/".$dir])){
        $localdir = $dir;
        if(strpos($dir,"/") > -1){
          $localdir = explode("/",$dir);
          $localdir = $localdir[0];
        }
        $res = Settings::getCached($this->area,$this->areaType,$this->dir."/".$localdir);
        $res->parent = $this;
        self::$instances[$this->areaType][$this->area][$this->dir."/".$dir] = $res;
        if(strpos($dir,"/") > -1){
          $res = $res->dir(substr($dir,strlen($localdir)));
        }
      }
      else{
        $res = self::$instances[$this->areaType][$this->area][$this->dir."/".$dir];
      }
      return $res;
    }

    public function cache(){
      if(self::$allowFileCache){
        Cache::setData("settings",$this->area."|".$this->areaType."|".$this->dir."|".self::getRoleID(),$this->properties);
      }
    }

    /**
     *
     * @return int 
     */
    protected static function getRoleID(){
      return User::Current()->role->ID;
    }

    /**
     *
     * @param string $area
     * @param string $areatype
     * @param string $dir
     * @return Settings 
     */
    protected static function getCached($area,$areatype,$dir){
      $res = null;
      $role = self::getRoleID();
      $res = new Settings();
      $res->setAreaType($areatype);
      $res->setArea($area);
      $res->setDir($dir);
      if(Cache::contains("settings",$area."|".$areatype."|".$dir."|".$role)){
        $res->properties = Cache::getData("settings",$area."|".$areatype."|".$dir."|".$role);
      }
     return $res;
    }

    public function __destruct(){
      $this->cache();
    }

    /**
     *
     * @param int $role
     * @return array 
     */
    public function getRows($role){
      $res  = array();
      $area = DataBase::Current()->EscapeString($this->area);
      $areatype = DataBase::Current()->EscapeString($this->areaType);
      $sql  = "SELECT DISTINCT property, description, type FROM {'dbprefix'}settings WHERE area = '".$area."' AND areaType = '".$areatype."' AND activated = 1";
      $rows = DataBase::Current()->ReadRows($sql);
      foreach($rows as $row){
        $property = array();
        $property['name']  = $row->property;
        $property['value'] = $this->get($row->property,$role,false);
        $property['description'] = $row->description;
        $property['type'] = $row->type;
        $res[] = $property;
      }
      return $res;
    }

    public static function forceReload(){
      self::$instances = null;
      self::$default = null;
      Cache::clear("settings");
    }

    /**
     *
     * @param string $key
     * @return string
     */
    public static function getValue($key){
      return self::getInstance()->get($key);
    }

  }
?>